package com.tvsinfo.jdk.demo.case7_parallel;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.LongStream;
import java.util.stream.Stream;

/**
 * 并行流与串行流
 */
public class Parallel1_Stream {

    public static void main(String[] args) {
        Parallel1_Stream streamParallel = new Parallel1_Stream();
        streamParallel.case2_parallelStream();
        streamParallel.case4_LongStream_parallel();
        streamParallel.case4_LongStream_rangeClosed();
    }

    /**
     * 使用示例
     */
    public void case1_parallelStream() {
        //生成集合
        List<ParallelCase> numbers = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            numbers.add(new ParallelCase(i));
        }

        long startTimes = System.currentTimeMillis();
        numbers.stream().forEach(ParallelCase::doWork);
        long endtimes = System.currentTimeMillis();
        System.out.println("stream-> startTime：" + startTimes + " end:" + endtimes + " done in：" + (endtimes - startTimes));


        startTimes = System.currentTimeMillis();
        numbers.parallelStream().forEach(ParallelCase::doWork);
        endtimes = System.currentTimeMillis();
        System.out.println("parallelStream-> startTime：" + startTimes + " end:" + endtimes + " done in：" + (endtimes - startTimes));


        startTimes = System.currentTimeMillis();
        numbers.stream().parallel().forEach(ParallelCase::doWork);
        endtimes = System.currentTimeMillis();
        System.out.println("stream().parallel()-> startTime：" + startTimes + " end:" + endtimes + " done in：" + (endtimes - startTimes));
    }

    /**
     * 拆箱与装箱示例
     */
    public void case2_parallelStream() {
        long startTimes = System.currentTimeMillis();
        long t1 = Stream.iterate(1L, aLong -> aLong + 1)
                .limit(1000)
                .parallel()
                .reduce(0L, Long::sum);
        long endTimes = System.currentTimeMillis();
        System.out.println("stream-> startTime：" + startTimes + " end:" + endTimes + " done in：" + (endTimes - startTimes) + "ms value:" + t1);

        startTimes = System.currentTimeMillis();
        long t2 = Stream.iterate(1L, aLong -> aLong + 1)
                .limit(1000)
                .reduce(0L, Long::sum);
        endTimes = System.currentTimeMillis();
        System.out.println("stream-> startTime：" + startTimes + " end:" + endTimes + " done in：" + (endTimes - startTimes) + "ms value:" + t2);
    }

    /**
     * 拆箱与装箱示例2
     */
    public void case3_parallelStream() {
        List<ParallelCase> numbers = new ArrayList<>();
        Random random = new Random();
        for (int i = 0; i < 100000; i++) {
            numbers.add(new ParallelCase(Integer.valueOf(random.nextInt(100000))));
        }
        long startTimes = System.currentTimeMillis();
        int t3 = numbers.stream().parallel().mapToInt(ParallelCase::getDoCondition).sum();
        long endTimes = System.currentTimeMillis();
        System.out.println("stream-> startTime：" + startTimes + " end:" + endTimes + " done in：" + (endTimes - startTimes) + "ms  value:" + t3);

        startTimes = System.currentTimeMillis();
        int t2 = numbers.stream().parallel().reduce(0, (parallelCase, parallelCase2) -> +parallelCase + parallelCase2.getDoCondition(), Integer::sum);
        endTimes = System.currentTimeMillis();
        System.out.println("stream-> startTime：" + startTimes + " end:" + endTimes + " done in：" + (endTimes - startTimes) + "ms  value:" + t2);

        startTimes = System.currentTimeMillis();
        Integer t = numbers.stream().reduce(0, (parallelCase, parallelCase2) -> +parallelCase + parallelCase2.getDoCondition(), Integer::sum);
        endTimes = System.currentTimeMillis();
        System.out.println("stream-> startTime：" + startTimes + " end:" + endTimes + " done in：" + (endTimes - startTimes) + "ms  value:" + t);

        startTimes = System.currentTimeMillis();
        int t4 = numbers.stream().parallel().map(ParallelCase::getDoCondition).reduce(0, Integer::sum);
        endTimes = System.currentTimeMillis();
        System.out.println("stream-> startTime：" + startTimes + " end:" + endTimes + " done in：" + (endTimes - startTimes) + "ms  value:" + t3);
    }

    /**
     * 使用拆箱流
     */
    public void case4_LongStream_parallel() {
        long startTimes = System.currentTimeMillis();
        long t1 = LongStream.iterate(1L, aLong -> aLong + 1)
                .limit(20000000)
                .parallel()
                .reduce(0L, Long::sum);
        long endTimes = System.currentTimeMillis();
        System.out.println("LongStream_parallel done in：" + (endTimes - startTimes) + "ms value:" + t1);

        startTimes = System.currentTimeMillis();
        long t2 = LongStream.iterate(1L, aLong -> aLong + 1)
                .limit(20000000)
                .reduce(0L, Long::sum);
        endTimes = System.currentTimeMillis();
        System.out.println("LongStream done in：" + (endTimes - startTimes) + "ms value:" + t2);
    }

    public void case4_LongStream_rangeClosed() {
        long startTimes = System.currentTimeMillis();
        long t1 = LongStream.rangeClosed(1L, 20000000)
                .parallel()
                .reduce(0L, Long::sum);
        long endTimes = System.currentTimeMillis();
        System.out.println("LongStream_rangeClosed parallel  done in：" + (endTimes - startTimes) + "ms value:" + t1);

        startTimes = System.currentTimeMillis();
        long t2 = LongStream.rangeClosed(1L, 20000000)
                .reduce(0L, Long::sum);
        endTimes = System.currentTimeMillis();
        System.out.println("LongStream_rangeClosed  done in：" + (endTimes - startTimes) + "ms value:" + t2);
    }


    public static class ParallelCase {
        private Integer doCondition;

        public ParallelCase(Integer doCondition) {
            this.doCondition = doCondition;
        }

        public Integer doWork() {
            try {
                Thread.sleep(10L);
                System.out.println("id:" + Thread.currentThread().getId() + " , name:" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return doCondition;
        }

        public Integer doWork2() {
            try {
                Thread.sleep(10L);
                System.out.println("id:" + Thread.currentThread().getId() + " , name:" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return doCondition;
        }

        public Integer getDoCondition() {
            return doCondition;
        }
    }

}
